
#pragma once

#include "gl/glew.h"
#include "ublocks.h"

#include <vector>
#include <string>
#include <map>

using namespace std;

namespace EggNine {

// Single pass technique
class IProgram {
protected:
    GLuint              m_programId;
    
    struct TexUnit {
        GLint   m_location;
        GLuint  m_unit;
        GLuint  m_sampler;
        GLenum  m_target;
    };
    map<string, TexUnit>  m_texUnits;
    map<string, GLint>  m_attribMap;
    vector<const UniformBlock*> m_uBlocks;

    mutable GLint       m_targetTex;
    mutable GLenum      m_targetType;

    const string    m_name;
    const string    m_alias;

    void SetSourceTextures() const;
    virtual void ResetStateToProgram() const=0;
    virtual void GetActiveUniforms(const UniformMap& uBlocks)=0;
    virtual void MapTextures() const;

public:
    IProgram(const string& name, const string& alias);
    virtual ~IProgram();
    
    GLint GetAttribLocation(const string& attr) const;

    void SetTargetTexture(GLuint texId, GLenum target) const;
    void SetTexture(const string& texName, GLuint texId) const;
    
    virtual void DrawPass(int pass=0) const = 0;

    void AttachGlobalUniforms(const UniformMap& uBlocks);

    void ResetToProgram() const;
};
typedef map<string, IProgram*> ProgramsMap;


} // EggNine